import { CanActivate, ExecutionContext, ForbiddenException, Injectable, UnauthorizedException } from '@nestjs/common'
import { Reflector } from '@nestjs/core'
import { Payload } from 'src/common/interfaces/auth.interface'
import { RbacService } from 'src/modules/rbac/services/rbac.service'

/**
 * 权限守卫
 * 用于接口权限校验，可集成RBAC等权限系统
 */
@Injectable()
export class PermissionsGuard implements CanActivate {
  constructor(
    private reflector: Reflector,
    private rbacService: RbacService,
  ) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const isPublic = this.reflector.getAllAndOverride<boolean>('isPublic', [context.getHandler(), context.getClass()])

    if (isPublic) {
      return true
    }
    // 获取请求对象和用户信息
    const request = context.switchToHttp().getRequest<{ user: Payload } & Request>()
    const user = request.user

    // 认证检查
    if (!user) throw new UnauthorizedException('用户未认证')

    // 获取路由元数据权限要求
    const requiredPermissions = this.reflector.get<string[]>('permissions', context.getHandler())

    // 无需权限的接口
    if (!requiredPermissions) return true

    // 是否为超级管理员
    const isSuperAdmin = await this.rbacService.isSuperAdmin(user.id)
    if (isSuperAdmin) return true

    // 权限校验
    const hasPermission = await Promise.all(
      requiredPermissions.map((p) => this.rbacService.hasPermission(user.id, p)),
    ).then((results) => results.some(Boolean))
    if (!hasPermission) throw new ForbiddenException('权限不足')
    return true
  }
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  catch(error: any) {
    throw new UnauthorizedException('获取用户权限失败')
  }
}
